#if defined(ARCTIC)
/**
 @file sys_at_port.c

 @date 2020-1-9

 @version v1.0

 The file contains TMM port APIs of sys layer
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_error.h"
#include "ctc_macro.h"
#include "sys_usw_port.h"
#include "sys_usw_chip.h"
#include "sys_usw_dmps.h"
#include "sys_usw_mac.h"

#define SYS_PORT_BASE_ON_PRI_COLOR(value) (CTC_XPIPE_MODE_2 == (value) || CTC_XPIPE_MODE_4 == (value) || CTC_XPIPE_MODE_5 == (value))
#define SYS_PORT_CPU_MAC_TXAQM_PORT_ID 32
#define SYS_PORT_PRIO_CLASS_NUM     8

extern int32
sys_at_queue_get_resrc(uint8 lchip, ctc_qos_resrc_t* p_resrc);

int32
sys_at_port_set_pause_speed(uint8 lchip, uint32 mac_id, void* p_data)
{
    uint16 index = 0;
    uint8 pp_id = 0;
    uint16 step = 0;
    uint32 cmd = 0;
    uint8 mac_idx = mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM); /*0-7*/
    uint32 pause_dec_value = 0;
    uint32 pause_pulse_sel = 0;
    sys_usw_port_mac_config_t* port_mac_config = (sys_usw_port_mac_config_t*)p_data;
    McMacPauseRxCtl_m mac_rx_pause_ctl;
    McMacPauseTxCtl_m mac_tx_pause_ctl;
#ifdef EMULATOR_ENV
    return CTC_E_NONE;
#endif
    switch (port_mac_config->speed_mode)
    {
    case CTC_PORT_SPEED_1G:
        pause_dec_value = 2;
        break;
    case CTC_PORT_SPEED_2G5:
        pause_dec_value = 5;
        break;
    case CTC_PORT_SPEED_10G:
        pause_dec_value = 20;
        break;
    case CTC_PORT_SPEED_20G:
        pause_dec_value = 40;
        break;
    case CTC_PORT_SPEED_40G:
        pause_dec_value = 20;
        pause_pulse_sel = 1;
        break;
    case CTC_PORT_SPEED_100G:
        pause_dec_value = 50;
        pause_pulse_sel = 1;
        break;
    case CTC_PORT_SPEED_5G:
        pause_dec_value = 10;
        break;
    case CTC_PORT_SPEED_25G:
        pause_dec_value = 50;
        break;
    case CTC_PORT_SPEED_50G:
        pause_dec_value = 25;
        pause_pulse_sel = 1;
        break;
    case CTC_PORT_SPEED_200G:
        pause_dec_value = 50;
        pause_pulse_sel = 2;
        break;
    case CTC_PORT_SPEED_400G:
        pause_dec_value = 100;
        pause_pulse_sel = 2;
        break;
    case CTC_PORT_SPEED_800G:
        pause_dec_value = 100;
        pause_pulse_sel = 3;
        break;
    default:
        pause_dec_value = 2;
        pause_pulse_sel = 0;
        break;
    }
    if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
    {
        ds_t ds;

        if (mac_id >= (SYS_CPU_MAC_ID_MIN + 2))
        {
            pp_id = SYS_PP_NUM(lchip) / 2;
        }
        step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
        cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, 0, DRV_CMD_PP_EN(cmd), &ds));
        SetSgmac0RxPauseCfg(V, cfgSgmac0RxPauseTimerDecValue_f, &ds, pause_dec_value);
        cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, 0, DRV_CMD_PP_EN(cmd), &ds));

        step = (Sgmac1TxPauseCfg_t - Sgmac0TxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
        cmd = DRV_IOR(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, 0, DRV_CMD_PP_EN(cmd), &ds));
        SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseTimerDecValue_f, &ds, pause_dec_value);
        cmd = DRV_IOW(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, 0, DRV_CMD_PP_EN(cmd), &ds));
    }
    else
    {
        if (mac_id >= MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP))
        {
            pp_id = SYS_PP_NUM(lchip) / 2;
        }
        index = (mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)) % DRV_TABLE_MAX_INDEX(lchip, McMacPauseRxCtl_t);
        cmd = DRV_IOR(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index, DRV_CMD_PP_EN(cmd), &mac_rx_pause_ctl));
        cmd = DRV_IOR(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index, DRV_CMD_PP_EN(cmd), &mac_tx_pause_ctl));

        step = (McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxPauseTimerDecValue_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxPauseTimerDecValue_f) * mac_idx;
        SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPauseTimerDecValue_f + step, &mac_rx_pause_ctl, pause_dec_value);
        /*Default disable flow ctl*/
        if (port_mac_config->is_init)
        {
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl, 0);
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl, 0);
        }
        step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_cfgMcMacTxPauseTimerDecValue_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseTimerDecValue_f) * mac_idx;
        SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacTxPauseTimerAdjValue_f + step, &mac_tx_pause_ctl, 0xFF00);/*for pressure flow to 0 */
        SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacTxPauseTimerDecValue_f + step, &mac_tx_pause_ctl, pause_dec_value);
        SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacPausePulseSel_f + step, &mac_tx_pause_ctl, pause_pulse_sel);
        cmd = DRV_IOW(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index, DRV_CMD_PP_EN(cmd), &mac_rx_pause_ctl));
        cmd = DRV_IOW(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index, DRV_CMD_PP_EN(cmd), &mac_tx_pause_ctl));
    }
    return CTC_E_NONE;
}

int32
_sys_at_port_flow_ctrl_cfg(uint8 lchip)
{
    uint8 gchip_id = 0;
    uint16 lport = 0;
    sys_port_info_t port_info = {0};
    sys_usw_port_mac_config_t port_mac_config = {0};
    Sgmac0RxPauseCfg_m sgmac_rx_pause_cfg;
    McMacPauseRxCtl_m mac_rx_pause_ctl;
    uint32 entry_num = 0;
    uint32 cmd = 0;
    uint16 index = 0;
    uint16 step = 0;

    sal_memset(&sgmac_rx_pause_cfg, 0, sizeof(sgmac_rx_pause_cfg));
    sal_memset(&mac_rx_pause_ctl, 0, sizeof(mac_rx_pause_ctl));

    port_mac_config.is_init = 1;

    SetSgmac0RxPauseCfg(V, cfgSgmac0RxPauseLockDetectTimer0_f, &sgmac_rx_pause_cfg, 0x10);
    SetSgmac0RxPauseCfg(V, cfgSgmac0RxPauseLockDetectTimer1_f, &sgmac_rx_pause_cfg, 0x10);

    step = McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxNormPauseEn_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f;
    for (index = 0; index < MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM); index++)
    {
        SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPauseLockDetectTimer0_f + step * index, &mac_rx_pause_ctl, 0x10);
        SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPauseLockDetectTimer1_f + step * index, &mac_rx_pause_ctl, 0x10);
    }

    step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t);
    for (index = 0; index <= (SYS_CPU_MAC_ID_MAX - SYS_CPU_MAC_ID_MIN); index++)
    {
        cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step * index, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sgmac_rx_pause_cfg));
    }

    cmd = DRV_IOW(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
    sys_usw_ftm_query_table_entry_num(lchip, McMacPauseRxCtl_t, &entry_num);
    for (index = 0; index < entry_num; index++)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mac_rx_pause_ctl));
    }

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, 0, &port_info));
        if (!(SYS_DMPS_NETWORK_PORT == port_info.port_type || SYS_DMPS_CPUMAC_NETWORK_PORT == port_info.port_type || SYS_DMPS_CPU_MAC_PORT == port_info.port_type))
        {
            continue;
        }
        port_mac_config.speed_mode = port_info.speed_mode;
        CTC_ERROR_RETURN(sys_at_port_set_pause_speed(lchip, port_info.mac_id, (void*)&port_mac_config));
    }

    return CTC_E_NONE;
}

int32
sys_at_port_flow_ctl_init(uint8 lchip)
{
    uint32 cmd = 0;
    RefDivMcMacPulse_m pause_pulse;
    RefDivMiscPulse_m cpumac_pause_pulse;
    NetRxCtl_m net_rx_ctl;
    ds_t ds;
    uint8 pp_id = 0;
    uint8 dp_id = 0;

    sal_memset(&ds, 0, sizeof(ds));
    sal_memset(&net_rx_ctl, 0, sizeof(net_rx_ctl));
    cmd = DRV_IOR(RefDivMcMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &pause_pulse));
    SetRefDivMcMacPulse(V, cfgRefDivMcMacPauseTimer0Pulse_f, &pause_pulse, 0x9F00); /* 1~25G */
    SetRefDivMcMacPulse(V, cfgRefDivMcMacPauseTimer1Pulse_f, &pause_pulse, 0x2700); /* 40~100G */
    SetRefDivMcMacPulse(V, cfgRefDivMcMacPauseTimer2Pulse_f, &pause_pulse, 0x1300); /* 200~400G */
    SetRefDivMcMacPulse(V, cfgRefDivMcMacPauseTimer3Pulse_f, &pause_pulse, 0x900); /* 800G */
    SetRefDivMcMacPulse(V, cfgResetDivMcMacPauseTimer0Pulse_f, &pause_pulse, 0);
    SetRefDivMcMacPulse(V, cfgResetDivMcMacPauseTimer1Pulse_f, &pause_pulse, 0);
    SetRefDivMcMacPulse(V, cfgResetDivMcMacPauseTimer2Pulse_f, &pause_pulse, 0);
    SetRefDivMcMacPulse(V, cfgResetDivMcMacPauseTimer3Pulse_f, &pause_pulse, 0);
    cmd = DRV_IOW(RefDivMcMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &pause_pulse));

    cmd = DRV_IOR(RefDivMiscPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &cpumac_pause_pulse));
    SetRefDivMiscPulse(V, cfgRefDivCpuMacPauseTimer0Pulse_f, &cpumac_pause_pulse, 0x9F00);/* 1~25G */
    SetRefDivMiscPulse(V, cfgRefDivCpuMacPauseTimer1Pulse_f, &cpumac_pause_pulse, 0x2700);/* 40~100G */
    SetRefDivMiscPulse(V, cfgRefDivCpuMacPauseTimer2Pulse_f, &cpumac_pause_pulse, 0x1300);/* 200~400G */
    SetRefDivMiscPulse(V, cfgRefDivCpuMacPauseTimer3Pulse_f, &cpumac_pause_pulse, 0x900);/* 800G */
    SetRefDivMiscPulse(V, cfgResetDivCpuMacPauseTimer0Pulse_f, &cpumac_pause_pulse, 0);
    SetRefDivMiscPulse(V, cfgResetDivCpuMacPauseTimer1Pulse_f, &cpumac_pause_pulse, 0);
    SetRefDivMiscPulse(V, cfgResetDivCpuMacPauseTimer2Pulse_f, &cpumac_pause_pulse, 0);
    SetRefDivMiscPulse(V, cfgResetDivCpuMacPauseTimer3Pulse_f, &cpumac_pause_pulse, 0);
    cmd = DRV_IOW(RefDivMiscPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &cpumac_pause_pulse));

    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        lchip = SYS_PP_BASE(lchip) + pp_id;
        for (dp_id = 0; dp_id < MCHIP_CAP(SYS_CAP_DP_MAX_NUM); dp_id++)
        {
            /*pause frame length could >=64*/
            cmd = DRV_IOR(NetRxCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &net_rx_ctl));
            SetNetRxCtl(V, cfgPfcEq64BytesEnable_f, &net_rx_ctl, 1);
            SetNetRxCtl(V, cfgPfcLt64BytesEnable_f, &net_rx_ctl, 1);
            SetNetRxCtl(V, cfgPfcGt64BytesEnable_f, &net_rx_ctl, 1);
            cmd = DRV_IOW(NetRxCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &net_rx_ctl));
        }
    }

    CTC_ERROR_RETURN(_sys_at_port_flow_ctrl_cfg(SYS_PP_BASE(lchip)));
    
    return CTC_E_NONE;
}

STATIC int32
sys_at_port_set_igs_flow_ctl_en(uint8 lchip, uint8 sub_chan, uint8 dp_id, uint32 mac_id, uint32 txaqm_port_id, ctc_port_fc_prop_t *fc_prop, uint8 is_recover)
{
    QMgrDeqFlowCtlEnUc_m qmgr_deq_flow_ctl;
    McMacPauseRxCtl_m mac_rx_pause_ctl;
    ds_t ds;
    uint32 flow_ctl_en_vec[2] = {0};
    uint32 field_val = 0;
    uint32 index = 0;
    uint32 cmd = 0;
    uint16 step = 0;
    uint16 step_1 = 0;
    uint8 pp_chan = sub_chan + dp_id * MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
    uint8 is_cpu_mac = (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX);
    uint8 old_is_pfc = 0;
    uint8 pfc_pri_vec = 0;
    uint8 pfc_class = 0;
    uint8 keep_enable = 0;

    pfc_class = fc_prop->priority_class_bmp ? fc_prop->pfc_class : fc_prop->priority_class;

    if (is_cpu_mac)
    {
        step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * ((mac_id - SYS_CPU_MAC_ID_MIN) % MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_CORE));
        cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &ds));
        old_is_pfc = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds);
    }
    else
    {
        step = (McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxPfcPauseEn_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f)
             * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
        index = (mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)) % DRV_TABLE_MAX_INDEX(lchip, McMacPauseRxCtl_t);
        cmd = DRV_IOR(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &mac_rx_pause_ctl));
        old_is_pfc = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl);
    }

    if (!fc_prop->enable && ((old_is_pfc && !fc_prop->is_pfc) || (!old_is_pfc && fc_prop->is_pfc)))
    {
        return CTC_E_NONE;
    }

    if (fc_prop->is_pfc && !is_recover)
    {
        DsQMgrRdFlowCtlMap0_m flow_ctl_map;
        uint32 tbl_id = dp_id ? DsQMgrRdFlowCtlMap1_t : DsQMgrRdFlowCtlMap0_t;

        step_1 = DsQMgrRdFlowCtlMap0_pfcPri_1_stallEn_f - DsQMgrRdFlowCtlMap0_pfcPri_0_stallEn_f;

        /* set priority map */
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &flow_ctl_map));

        if (0 == fc_prop->priority_class_bmp)
        {
            field_val = 0;
            CTC_BIT_SET(field_val, pfc_class);
        }
        else
        {
            field_val = fc_prop->priority_class_bmp;
        }

        if (!fc_prop->enable)
        {
            field_val = ~field_val & GetDsQMgrRdFlowCtlMap0(V, pfcPri_0_stallEn_f + step_1 * pfc_class, &flow_ctl_map);
            keep_enable = !!field_val;
        }
        SetDsQMgrRdFlowCtlMap0(V, pfcPri_0_stallEn_f + step_1 * pfc_class, &flow_ctl_map, field_val);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &flow_ctl_map));

        if (keep_enable)
        {
            return CTC_E_NONE;
        }
    }

    /*FC/PFC enable/disable*/
    if (is_cpu_mac)
    {
        if (fc_prop->is_pfc)
        {
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds, 1);
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds, 0);
            pfc_pri_vec = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds);
            (fc_prop->enable) ? CTC_BIT_SET(pfc_pri_vec, pfc_class) : CTC_BIT_UNSET(pfc_pri_vec, pfc_class);
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f , &ds, pfc_pri_vec);
        }
        else
        {
            field_val = (fc_prop->enable) ? 1 : 0;
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds, field_val);
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds, 0);
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f , &ds, 0);
        }
        cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &ds));
    }
    else
    {
        if (fc_prop->is_pfc)
        {
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl, 1);
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl, 0);
            pfc_pri_vec = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl);
            (fc_prop->enable) ? CTC_BIT_SET(pfc_pri_vec, pfc_class): CTC_BIT_UNSET(pfc_pri_vec, pfc_class);
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl, pfc_pri_vec);
        }
        else
        {
            field_val = (fc_prop->enable) ? 1 : 0;
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl, field_val);
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl, 0);
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl, 0);
        }

        cmd = DRV_IOW(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &mac_rx_pause_ctl));
    }

    if((old_is_pfc && !fc_prop->is_pfc) || fc_prop->is_pfc)
    {
        /*config group flowctl enable*/
        cmd = DRV_IOR(QMgrDeqFlowCtlEnUc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &qmgr_deq_flow_ctl));
        GetQMgrDeqFlowCtlEnUc(A, flowCtlEnVec_f, &qmgr_deq_flow_ctl, flow_ctl_en_vec);
        (pfc_pri_vec && fc_prop->is_pfc) ? CTC_BMP_SET(flow_ctl_en_vec, pp_chan) : CTC_BMP_UNSET(flow_ctl_en_vec, pp_chan);
        SetQMgrDeqFlowCtlEnUc(A, flowCtlEnVec_f, &qmgr_deq_flow_ctl, flow_ctl_en_vec);
        cmd = DRV_IOW(QMgrDeqFlowCtlEnUc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &qmgr_deq_flow_ctl));
    }

    if (old_is_pfc && !fc_prop->is_pfc)
    {
        field_val = 0;
        cmd = DRV_IOW(DsQMgrFlowCtlStateUc_t, DsQMgrFlowCtlStateUc_stallValid_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &field_val));
    }

    return CTC_E_NONE;
}

STATIC int32
sys_at_port_set_egs_flow_ctl_en(uint8 lchip, uint8 sub_chan, uint8 dp_id, uint32 mac_id, uint32 txaqm_port_id, ctc_port_fc_prop_t *fc_prop)
{
    DsIrmPortFlowControlThrdProfile_m irm_thrd_profile;
    DsIrmPortStallState_m irm_stall_state;
    NetRxForcePauseReq_m netrx_pause_req;
    DsNetRxPauseStats_m netrx_pause_stats;
    DsIrmPortStallEn_m port_stall;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint16 step = 0;
    uint8 switch_type = 0;
    uint8 old_is_pfc = 0;

    /*get old Irm FC/PFC enable/disable*/
    cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &port_stall));
    old_is_pfc = GetDsIrmPortStallEn(V, portPriEnVec_f, &port_stall);

    switch_type = ((old_is_pfc && !fc_prop->is_pfc) || (!old_is_pfc && fc_prop->is_pfc));
    if (!fc_prop->enable)
    {
        if (switch_type)
        {
            return CTC_E_NONE;
        }

        if (fc_prop->is_pfc)
        {
            /* set xon/xoff to max */
            cmd = DRV_IOR(DsIrmPortFlowControlThrdProfile_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_thrd_profile));

            step = DsIrmPortFlowControlThrdProfile_g_1_xoffThrd_f - DsIrmPortFlowControlThrdProfile_g_0_xoffThrd_f;
            SetDsIrmPortFlowControlThrdProfile(V, g_0_xonThrd_f + step * fc_prop->priority_class, &irm_thrd_profile, 0x3FFFF);
            SetDsIrmPortFlowControlThrdProfile(V, g_0_xoffThrd_f + step * fc_prop->priority_class, &irm_thrd_profile, 0x3FFFF);

            cmd = DRV_IOW(DsIrmPortFlowControlThrdProfile_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_thrd_profile));

            /* clear stall state */
            sal_memset(&netrx_pause_stats, 0, sizeof(netrx_pause_stats));
            SetDsNetRxPauseStats(V, pauseStatsWrEn_f, &netrx_pause_stats, 1);
            SetDsNetRxPauseStats(V, pauseStatsPort_f, &netrx_pause_stats, txaqm_port_id);
            SetDsNetRxPauseStats(V, pauseStatsStallVec_f, &netrx_pause_stats, 1 << fc_prop->priority_class);
            cmd = DRV_IOW(DsNetRxPauseStats_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_pause_stats));
        
            /* send xon pause frame */
            sal_memset(&netrx_pause_req, 0, sizeof(netrx_pause_req));
            SetNetRxForcePauseReq(V, cfgForcePauseReqPortId_f, &netrx_pause_req, txaqm_port_id);
            cmd = DRV_IOW(NetRxForcePauseReq_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_pause_req));
        }
        else
        {
            /* disable port fc */
            sal_memset(&port_stall, 0, sizeof(port_stall));
            cmd = DRV_IOW(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &port_stall));
            
            /* clear irm stall state */
            sal_memset(&irm_stall_state, 0, sizeof(irm_stall_state));
            cmd = DRV_IOW(DsIrmPortStallState_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_stall_state));
            
            /* clear netrx pause state */
            sal_memset(&netrx_pause_stats, 0, sizeof(netrx_pause_stats));
            SetDsNetRxPauseStats(V, pauseStatsWrEn_f, &netrx_pause_stats, 1);
            SetDsNetRxPauseStats(V, pauseStatsPort_f, &netrx_pause_stats, txaqm_port_id);
            SetDsNetRxPauseStats(V, pauseStatsStallVec_f, &netrx_pause_stats, 0xFF);
            cmd = DRV_IOW(DsNetRxPauseStats_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_pause_stats));

            /* send xon pause frame */
            sal_memset(&netrx_pause_req, 0, sizeof(netrx_pause_req));
            SetNetRxForcePauseReq(V, cfgForcePauseReqPortId_f, &netrx_pause_req, txaqm_port_id);
            cmd = DRV_IOW(NetRxForcePauseReq_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_pause_req));
        }
        return CTC_E_NONE;
    }
    else
    {
        ctc_qos_resrc_t qos_resrc;

        sal_memset(&qos_resrc, 0, sizeof(qos_resrc));
        qos_resrc.cfg_type = CTC_QOS_RESRC_CFG_FLOW_CTL;
        qos_resrc.u.flow_ctl.is_pfc = fc_prop->is_pfc;
        qos_resrc.u.flow_ctl.priority_class = fc_prop->priority_class;
        qos_resrc.u.flow_ctl.gport = fc_prop->gport;

        CTC_ERROR_RETURN(sys_at_queue_get_resrc(lchip, &qos_resrc));

        if (!switch_type)
        {
            /* enable port fc, set priEnVec */
            sal_memset(&port_stall, 0, sizeof(port_stall));
            SetDsIrmPortStallEn(V, portFcEn_f, &port_stall, 1);
            SetDsIrmPortStallEn(V, portPriEnVec_f, &port_stall, fc_prop->is_pfc ? 0xFF : 0);
            cmd = DRV_IOW(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &port_stall));

            /* set priority thrd */
            cmd = DRV_IOR(DsIrmPortFlowControlThrdProfile_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_thrd_profile));
            step = DsIrmPortFlowControlThrdProfile_g_1_xoffThrd_f - DsIrmPortFlowControlThrdProfile_g_0_xoffThrd_f;
            SetDsIrmPortFlowControlThrdProfile(V, g_0_xonThrd_f + step * (fc_prop->is_pfc ? fc_prop->priority_class : 0), &irm_thrd_profile, qos_resrc.u.flow_ctl.xon_thrd);
            SetDsIrmPortFlowControlThrdProfile(V, g_0_xoffThrd_f + step * (fc_prop->is_pfc ? fc_prop->priority_class : 0), &irm_thrd_profile, qos_resrc.u.flow_ctl.xoff_thrd);
            cmd = DRV_IOW(DsIrmPortFlowControlThrdProfile_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_thrd_profile));
        }
        else
        {
            NetRxPauseReqCtl_m netrx_req_ctl;
            McMacPauseTxCtl_m mac_tx_ctl;
            uint32 pause_mask = 0;
            uint8 i = 0;
            uint8 is_cpu_mac = (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX);

            /* do not response to IRM request */
            cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_req_ctl));
            pause_mask = GetNetRxPauseReqCtl(V, bsPauseMaskBmp_f, &netrx_req_ctl);
            CTC_BIT_SET(pause_mask, sub_chan);
            SetNetRxPauseReqCtl(V, bsPauseMaskBmp_f, &netrx_req_ctl, pause_mask);
            cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_req_ctl));

            /* clear net rx stall state */
            sal_memset(&netrx_pause_stats, 0, sizeof(netrx_pause_stats));
            SetDsNetRxPauseStats(V, pauseStatsWrEn_f, &netrx_pause_stats, 1);
            SetDsNetRxPauseStats(V, pauseStatsPort_f, &netrx_pause_stats, txaqm_port_id);
            SetDsNetRxPauseStats(V, pauseStatsStallVec_f, &netrx_pause_stats, fc_prop->is_pfc ? 1 : 0xFF);
            cmd = DRV_IOW(DsNetRxPauseStats_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_pause_stats));

            /* send xon pause frame */
            sal_memset(&netrx_pause_req, 0, sizeof(netrx_pause_req));
            SetNetRxForcePauseReq(V, cfgForcePauseReqPortId_f, &netrx_pause_req, txaqm_port_id);
            cmd = DRV_IOW(NetRxForcePauseReq_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_pause_req));

            /* set all thrd to MAX */
            sal_memset(&irm_thrd_profile, 0, sizeof(irm_thrd_profile));
            step = DsIrmPortFlowControlThrdProfile_g_1_xoffThrd_f - DsIrmPortFlowControlThrdProfile_g_0_xoffThrd_f;
            for (i=0;i<8;i++)
            {
                SetDsIrmPortFlowControlThrdProfile(V, g_0_xonThrd_f + step * i, &irm_thrd_profile, 0x3FFFF);
                SetDsIrmPortFlowControlThrdProfile(V, g_0_xoffThrd_f + step * i, &irm_thrd_profile, 0x3FFFF);
            }
            cmd = DRV_IOW(DsIrmPortFlowControlThrdProfile_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_thrd_profile));

            /* disable port fc, set priEnVec, clear irm port stall, enable port fc */
            sal_memset(&port_stall, 0, sizeof(port_stall));
            SetDsIrmPortStallEn(V, portFcEn_f, &port_stall, 0);
            SetDsIrmPortStallEn(V, portPriEnVec_f, &port_stall, fc_prop->is_pfc ? 0xFF : 0);
            cmd = DRV_IOW(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &port_stall));

            sal_memset(&irm_stall_state, 0, sizeof(irm_stall_state));
            cmd = DRV_IOW(DsIrmPortStallState_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_stall_state));

            SetDsIrmPortStallEn(V, portFcEn_f, &port_stall, 1);
            cmd = DRV_IOW(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &port_stall));

            /* set priority thrd */
            SetDsIrmPortFlowControlThrdProfile(V, g_0_xonThrd_f + step * (fc_prop->is_pfc ? fc_prop->priority_class : 0), &irm_thrd_profile, qos_resrc.u.flow_ctl.xon_thrd);
            SetDsIrmPortFlowControlThrdProfile(V, g_0_xoffThrd_f + step * (fc_prop->is_pfc ? fc_prop->priority_class : 0), &irm_thrd_profile, qos_resrc.u.flow_ctl.xoff_thrd);
            cmd = DRV_IOW(DsIrmPortFlowControlThrdProfile_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_thrd_profile));

            /* set netrx / mac pause type */
            if (is_cpu_mac)
            {
                ds_t ds;

                field_val = fc_prop->is_pfc ? 1 : 0;

                SetNetRxPauseReqCtl(V, cfgCpuMacPauseType_f, &netrx_req_ctl, field_val);
                cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_req_ctl));

                step = (Sgmac1TxPauseCfg_t - Sgmac0TxPauseCfg_t) * ((mac_id - SYS_CPU_MAC_ID_MIN) % MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_CORE));
                cmd = DRV_IOR(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &ds));
                SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseType_f, &ds, field_val);
                cmd = DRV_IOW(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &ds));
            }
            else
            {
                uint32 index = (mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)) % DRV_TABLE_MAX_INDEX(lchip, McMacPauseTxCtl_t);

                field_val = GetNetRxPauseReqCtl(V, netRxPauseType_f, &netrx_req_ctl);
                fc_prop->is_pfc ? CTC_BIT_SET(field_val, txaqm_port_id) : CTC_BIT_UNSET(field_val, txaqm_port_id);
                SetNetRxPauseReqCtl(V, netRxPauseType_f, &netrx_req_ctl, field_val);
                cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_req_ctl));

                cmd = DRV_IOR(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_DP_EN(cmd, dp_id), &mac_tx_ctl));
                step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_cfgMcMacTxPauseType_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f);
                SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f + step * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)), &mac_tx_ctl, fc_prop->is_pfc);
                cmd = DRV_IOW(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_DP_EN(cmd, dp_id), &mac_tx_ctl));
            }

            /* response IRM request */
            CTC_BIT_UNSET(pause_mask, sub_chan);
            SetNetRxPauseReqCtl(V, bsPauseMaskBmp_f, &netrx_req_ctl, pause_mask);
            cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &netrx_req_ctl));
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_port_set_obmfc_en(uint8 lchip, uint8 dp_id, uint32 mac_id, uint32 txaqm_port_id, ctc_port_fc_prop_t *fc_prop)
{
    uint32 rx_pause_req_en[5] = {0};
    NetRxPauseReqCtl_m net_rx_pause_ctl;
    McMacPauseTxCtl_m mac_tx_ctl;
    NetRxPausePriRemap_m net_rx_pause_pri_remap;
    uint32 field_val = 0;
    uint16 index     = 0;
    uint16 step      = 0;
    uint32 cmd       = 0;

    if (mac_id >= SYS_CPU_MAC_ID_MIN || fc_prop->dir != CTC_EGRESS)
    {
        return CTC_E_INVALID_CONFIG;
    }

    cmd = DRV_IOR(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, txaqm_port_id, DRV_CMD_DP_EN(cmd, dp_id), &net_rx_pause_pri_remap));
    SetNetRxPausePriRemap(V, prio_f, &net_rx_pause_pri_remap, fc_prop->is_pfc && fc_prop->enable ? fc_prop->priority_class_bmp : 0);
    cmd = DRV_IOW(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, txaqm_port_id, DRV_CMD_DP_EN(cmd, dp_id), &net_rx_pause_pri_remap));

    if(fc_prop->enable)
    {
        /*change pause type*/
        cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &net_rx_pause_ctl));
        field_val = GetNetRxPauseReqCtl(V, netRxPauseType_f, &net_rx_pause_ctl);
        fc_prop->is_pfc ? CTC_BIT_SET(field_val, txaqm_port_id) : CTC_BIT_UNSET(field_val, txaqm_port_id);
        SetNetRxPauseReqCtl(V, netRxPauseType_f, &net_rx_pause_ctl, field_val);
        cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &net_rx_pause_ctl));

        index = (mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)) % DRV_TABLE_MAX_INDEX(lchip, McMacPauseTxCtl_t);
        cmd = DRV_IOR(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_DP_EN(cmd, dp_id), &mac_tx_ctl));
        step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_cfgMcMacTxPauseType_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f);
        SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f + step * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)), &mac_tx_ctl, fc_prop->is_pfc);
        cmd = DRV_IOW(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_DP_EN(cmd, dp_id), &mac_tx_ctl));
    }

    cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd,dp_id), &net_rx_pause_ctl));
    GetNetRxPauseReqCtl(A, netRxPauseReqEn_f, &net_rx_pause_ctl, rx_pause_req_en);
    fc_prop->enable ? CTC_BMP_SET(rx_pause_req_en, txaqm_port_id)
                    : CTC_BMP_UNSET(rx_pause_req_en, txaqm_port_id);
    SetNetRxPauseReqCtl(A, netRxPauseReqEn_f, &net_rx_pause_ctl, rx_pause_req_en);
    cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd,dp_id), &net_rx_pause_ctl));
    /*diable:force mac sending xon pause*/
    if (!fc_prop->enable)
    {
        field_val = 0;
        cmd = DRV_IOW(NetRxNetPriLog_t, NetRxNetPriLog_data_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, txaqm_port_id, DRV_CMD_DP_EN(cmd,dp_id), &field_val));

        cmd = DRV_IOW(NetRxForcePauseReq_t, NetRxForcePauseReq_cfgForcePauseReqPortId_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd,dp_id), &txaqm_port_id));

        field_val = 0;
        index = (mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)) % DRV_TABLE_MAX_INDEX(lchip, McMacPauseRxCtl_t);
        step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_dbgMcMacTxPauseCurStatus_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseCurStatus_f)
                     * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
        cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseCurStatus_f + step);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &field_val));
        cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseLogStatus_f + step);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &field_val));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_port_get_obmfc_en(uint8 lchip, uint8 dp_id, uint32 mac_id, uint32 txaqm_port_id, ctc_port_fc_prop_t *fc_prop)
{
    uint32 cmd = 0;
    uint32 rx_pause_req_en[5] = {0};
    NetRxPauseReqCtl_m net_rx_pause_ctl;
    NetRxPausePriRemap_m net_rx_pause_pri_remap;

    if (mac_id >= SYS_CPU_MAC_ID_MIN || fc_prop->dir != CTC_EGRESS)
    {
        return CTC_E_INVALID_CONFIG;
    }

    cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd,dp_id), &net_rx_pause_ctl));
    GetNetRxPauseReqCtl(A, netRxPauseReqEn_f, &net_rx_pause_ctl, rx_pause_req_en);
    fc_prop->enable = CTC_BMP_ISSET(rx_pause_req_en, txaqm_port_id) ? 1 : 0;

    cmd = DRV_IOR(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, txaqm_port_id, cmd, &net_rx_pause_pri_remap));
    fc_prop->priority_class_bmp = GetNetRxPausePriRemap(V, prio_f, &net_rx_pause_pri_remap);
    return CTC_E_NONE;
}

int32
sys_at_port_set_flow_ctl_en(uint8 lchip, void* p_fc_prop, uint8 is_recover)
{
    uint32 dp_id = 0;
    uint32 pp_id = 0;
    uint32 mac_id = 0;
    ctc_port_fc_prop_t *fc_prop = (ctc_port_fc_prop_t *)p_fc_prop;
    uint32 sub_chan = 0;
    uint32 txaqm_port_id = 0;
    uint16 lport = 0;
    sys_port_info_t port_info = {0};

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set gport:0x%04X \n", fc_prop->gport);

    if(fc_prop->is_oobfc || CTC_PORT_FC_TYPE_OOB == fc_prop->type)
    {
        return CTC_E_NOT_SUPPORT;
    }

    if (fc_prop->priority_class_bmp)
    {
        if ( !(CTC_INGRESS == fc_prop->dir && CTC_PORT_FC_TYPE_NORMAL == fc_prop->type  && fc_prop->is_pfc)
            || (fc_prop->priority_class_bmp >> SYS_PORT_PRIO_CLASS_NUM))
        {
            return CTC_E_INVALID_CONFIG;
        }
        CTC_MAX_VALUE_CHECK(fc_prop->pfc_class, SYS_PORT_PRIO_CLASS_NUM - 1);
    }
    else
    {
        CTC_MAX_VALUE_CHECK(fc_prop->priority_class, SYS_PORT_PRIO_CLASS_NUM - 1);
    }

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(fc_prop->gport, lchip, lport);
    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, 0, &port_info));
    if (!(SYS_DMPS_NETWORK_PORT == port_info.port_type || SYS_DMPS_CPUMAC_NETWORK_PORT == port_info.port_type || SYS_DMPS_CPU_MAC_PORT == port_info.port_type))
    {
        return CTC_E_INVALID_PORT;
    }
    mac_id = port_info.mac_id;
    sub_chan = port_info.sub_chan_id;
    pp_id = port_info.pp_id;
    dp_id = port_info.dp_id;
    lchip = SYS_PP_BASE(lchip) + pp_id;

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "mac_id:%d\n", mac_id);

    if (CTC_PORT_FC_TYPE_OBM == fc_prop->type && (CTC_EGRESS != fc_prop->dir || mac_id >= SYS_CPU_MAC_ID_MIN))
    {
        return CTC_E_INVALID_CONFIG;
    }

    if ((CTC_INGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
    {
        txaqm_port_id = (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX) ? SYS_PORT_CPU_MAC_TXAQM_PORT_ID : port_info.mac_client_id;
        CTC_ERROR_RETURN(sys_at_port_set_igs_flow_ctl_en(lchip, sub_chan, dp_id, mac_id, txaqm_port_id, fc_prop, is_recover));
    }

    if ((CTC_EGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
    {
        txaqm_port_id = (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX) ? SYS_PORT_CPU_MAC_TXAQM_PORT_ID : port_info.rx_mac_client_id;
        if(CTC_PORT_FC_TYPE_OBM == fc_prop->type)
        {
            return _sys_at_port_set_obmfc_en(lchip, dp_id, mac_id, txaqm_port_id, fc_prop);
        }
        CTC_ERROR_RETURN(sys_at_port_set_egs_flow_ctl_en(lchip, sub_chan, dp_id, mac_id, txaqm_port_id, fc_prop));
    }

    return CTC_E_NONE;
}

int32
sys_at_port_get_flow_ctl_en(uint8 lchip, void* p_fc_prop)
{
    uint32 pp_id = 0;
    uint32 sub_chan = 0;
    uint32 dp_id = 0;
    uint16 step = 0;
    uint32 mac_id = 0;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint32 rx_pause_type = 0;
    uint32 index = 0;
    NetRxPauseReqCtl_m  net_rx_pause_ctl;
    McMacPauseRxCtl_m mac_rx_pause_ctl;
    DsIrmPortStallEn_m  irm_stall_en;
    ctc_port_fc_prop_t *fc_prop = (ctc_port_fc_prop_t *)p_fc_prop;
    ds_t  ds;
    uint32 txaqm_port_id = 0;
    uint16 lport = 0;
    uint8 is_cpu_mac = 0;
    sys_port_info_t port_info = {0};

    sal_memset(&ds, 0, sizeof(ds));
    sal_memset(&irm_stall_en, 0, sizeof(DsIrmPortStallEn_m));
    sal_memset(&net_rx_pause_ctl, 0, sizeof(NetRxPauseReqCtl_m));
    sal_memset(&mac_rx_pause_ctl, 0, sizeof(McMacPauseRxCtl_m));
    CTC_MAX_VALUE_CHECK(fc_prop->priority_class, SYS_PORT_PRIO_CLASS_NUM - 1);
    if(fc_prop->is_oobfc)
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(fc_prop->gport, lchip, lport);
    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, 0, &port_info));
    if (!(SYS_DMPS_NETWORK_PORT == port_info.port_type || SYS_DMPS_CPUMAC_NETWORK_PORT == port_info.port_type || SYS_DMPS_CPU_MAC_PORT == port_info.port_type))
    {
        return CTC_E_INVALID_PORT;
    }
    mac_id = port_info.mac_id;
    sub_chan = port_info.sub_chan_id;
    pp_id = port_info.pp_id;
    dp_id = port_info.dp_id;
    lchip = SYS_PP_BASE(lchip) + pp_id;

    is_cpu_mac = mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX;

    if (!is_cpu_mac)
    {
        cmd = DRV_IOR(DsNetRxChanToPortMap_t, DsNetRxChanToPortMap_portId_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &txaqm_port_id));
    }

    if(CTC_PORT_FC_TYPE_OBM == fc_prop->type)
    {
        return _sys_at_port_get_obmfc_en(lchip, dp_id, mac_id, txaqm_port_id, fc_prop);
    }

    if (CTC_INGRESS == fc_prop->dir)
    {
        if (is_cpu_mac)
        {
            /*FC/PFC enable/disable*/
            step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * ((mac_id - SYS_CPU_MAC_ID_MIN) % MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_CORE));
            cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &ds));
            field_val = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds);

            if (fc_prop->is_pfc && CTC_IS_BIT_SET(field_val, (fc_prop->priority_class)))
            {
                fc_prop->enable = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds);
            }
            else if(!fc_prop->is_pfc)
            {
                fc_prop->enable = GetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds);
            }
        }
        else
        {
            index = (mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)) % DRV_TABLE_MAX_INDEX(lchip, McMacPauseRxCtl_t);

            step = (McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxPfcPauseEn_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f)
                 * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));

            /*FC/PFC enable/disable*/
            cmd = DRV_IOR(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &mac_rx_pause_ctl));
            field_val = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl);

            if (fc_prop->is_pfc && CTC_IS_BIT_SET(field_val, (fc_prop->priority_class)))
            {
                fc_prop->enable = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl);
            }
            else if(!fc_prop->is_pfc)
            {
                fc_prop->enable = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl);
            }
        }

        /* get priority map */
        if (fc_prop->is_pfc)
        {
            DsQMgrRdFlowCtlMap0_m flow_ctl_map;
            uint32 tbl_id = dp_id ? DsQMgrRdFlowCtlMap1_t : DsQMgrRdFlowCtlMap0_t;

            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &flow_ctl_map));
            step = DsQMgrRdFlowCtlMap0_pfcPri_1_stallEn_f - DsQMgrRdFlowCtlMap0_pfcPri_0_stallEn_f;
            fc_prop->priority_class_bmp = GetDsQMgrRdFlowCtlMap0(V, pfcPri_0_stallEn_f + step * fc_prop->priority_class, &flow_ctl_map);
        }
    }
    
    if (CTC_EGRESS == fc_prop->dir)
    {
        /*Rx port pause type: fc/pfc*/
        cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), &net_rx_pause_ctl));

        /*Irm FC/PFC enable/disable*/
        cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_stall_en));

        rx_pause_type = (is_cpu_mac && GetNetRxPauseReqCtl(V, cfgCpuMacPauseType_f, &net_rx_pause_ctl))
                      ||(!is_cpu_mac && CTC_IS_BIT_SET(GetNetRxPauseReqCtl(V, netRxPauseType_f, &net_rx_pause_ctl), txaqm_port_id));

        if (fc_prop->is_pfc && rx_pause_type)
        {
            field_val = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
            if (CTC_IS_BIT_SET(field_val, fc_prop->priority_class))
            {
                DsIrmPortFlowControlThrdProfile_m irm_thrd_profile;
                cmd = DRV_IOR(DsIrmPortFlowControlThrdProfile_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, DRV_CMD_DP_EN(cmd, dp_id), &irm_thrd_profile));
                step = DsIrmPortFlowControlThrdProfile_g_1_xoffThrd_f - DsIrmPortFlowControlThrdProfile_g_0_xoffThrd_f;
                
                fc_prop->enable = (0x3FFFF != GetDsIrmPortFlowControlThrdProfile(V, g_0_xoffThrd_f + step * fc_prop->priority_class, &irm_thrd_profile))
                                ||(0x3FFFF != GetDsIrmPortFlowControlThrdProfile(V, g_0_xonThrd_f + step * fc_prop->priority_class, &irm_thrd_profile));
            }
        }
        else if(!fc_prop->is_pfc && !rx_pause_type)
        {
            field_val = GetDsIrmPortStallEn(V, portFcEn_f, &irm_stall_en);
            fc_prop->enable = field_val;
        }
    }

    return CTC_E_NONE;
}

int32
sys_at_port_set_xpipe_en(uint8 lchip, uint32 gport, uint32 value)
{
    uint8  index     = 0;
    uint8  dp_id     = 0;
    uint8  pp_id     = 0;
    uint8  mac_num   = 0;
    uint8  chan_num  = 0;
    uint8  txqm_id   = 0;
    uint16 sub_chan  = 0;
    uint16 split_en  = 0;
    uint32 cmd       = 0;
    uint32 step      = 0;
    uint32 enable    = 0;
    uint32 tbl_id    = 0;
    uint32 tmp_value = 0;
    uint32 channel[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};    /* 0: low prio channel(origin channel), 1: high prio channel */
    uint32 mac_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT]  = {0};    /* per dp mac client id value 0-31,0: low prio mac, 1: high prio mac(origin mac) */
    DsNetRxBufAdmissionCtl_m adm_ctl;
    ds1_t ds = {0};

    /* per dp table NetRxPortSplitEnCtl, DsNetRxPriorityChannelRemap0, DsNetRxPriorityChannelRemap1 
                 NetTxPortSplitEnCtl, DsNetTxPriorityPortRemap0, DsNetTxPriorityPortRemap1 */
    /* per pp table DsMcQWriteGuarantee, McQWriteGuaranteeCtl, McQWritePortChannelMap, IpeHeaderAdjustChannelPortMap */

    CTC_ERROR_RETURN(sys_usw_port_api_get_mac(lchip, 1, gport, mac_id, &mac_num));
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 1, gport, channel , &chan_num));
    CTC_ERROR_RETURN(sys_usw_port_api_get_sub_chan_by_chan(lchip, 1, channel[0], &sub_chan, &pp_id, &dp_id));
    lchip = SYS_PP_BASE(lchip) + pp_id;

    index   = mac_id[mac_num - 1] % MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM);
    txqm_id = mac_id[mac_num - 1] / MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM);

    /*1. cfg netrx mapping NetRxPortSplitEnCtl(per dp) DsNetRxPriorityChannelRemap(per dp TXQM0) 
    mac 0 and mac 1 is equal*/
    step = NetRxPortSplitEnCtl_portSplitEn1_f - NetRxPortSplitEnCtl_portSplitEn0_f;
    cmd = DRV_IOR(NetRxPortSplitEnCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), ds));
    split_en = GetNetRxPortSplitEnCtl(V, portSplitEn0_f + step * txqm_id, ds);
    (mac_num > 1) ? CTC_BIT_SET(split_en, index) : CTC_BIT_UNSET(split_en, index);
    SetNetRxPortSplitEnCtl(V, portSplitEn0_f + step * txqm_id, ds, split_en);
    cmd = DRV_IOW(NetRxPortSplitEnCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), ds));

    /*2. match redirect to low priortiy channel need to modify */
    step = DsNetRxPriorityChannelRemap1_t - DsNetRxPriorityChannelRemap0_t;
    tbl_id = DsNetRxPriorityChannelRemap0_t + txqm_id * step;
    SetDsNetRxPriorityChannelRemap0(V, port_f, ds, mac_id[0]);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_DP_EN(cmd, dp_id), ds));

    /*3. set srcGuaranteeEn IpeHeaderAdjustChannelPortMap(per pp) 
         index(6,0) = {islog, dp_id, sub_channel(dp_chan)}*/
    step = IpeHeaderAdjustChannelPortMap_g_1_srcGuaranteeEn_f - IpeHeaderAdjustChannelPortMap_g_0_srcGuaranteeEn_f;

    index  = (dp_id << 5) | sub_chan;
    cmd = DRV_IOR(IpeHeaderAdjustChannelPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (index & 0x1F), DRV_CMD_PP_EN(cmd), ds));
    SetIpeHeaderAdjustChannelPortMap(V, g_0_srcGuaranteeEn_f + step * ((index>>5)&0x3), ds, (CTC_PORT_XPIPE_TYPE_2 == value || CTC_PORT_XPIPE_TYPE_6 == value) ? 0 : 1);
    cmd = DRV_IOW(IpeHeaderAdjustChannelPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (index & 0x1F), DRV_CMD_PP_EN(cmd), ds));

    if (CTC_PORT_XPIPE_TYPE_2 == value)
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_sub_chan_by_chan(lchip, 1, channel[chan_num-1], &sub_chan, &pp_id, &dp_id));
        index  = (dp_id << 5) | sub_chan;
        cmd = DRV_IOR(IpeHeaderAdjustChannelPortMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, (index & 0x1F), DRV_CMD_PP_EN(cmd), ds));
        SetIpeHeaderAdjustChannelPortMap(V, g_0_srcGuaranteeEn_f + step * ((index>>5)&0x3), ds, 1);
        cmd = DRV_IOW(IpeHeaderAdjustChannelPortMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, (index & 0x1F), DRV_CMD_PP_EN(cmd), ds));
    }

    /*4.classify base on fields NetRxPriorityChannelEn(per dp)*/
    tmp_value = (CTC_PORT_XPIPE_TYPE_2 == value || CTC_PORT_XPIPE_TYPE_6 == value) ? 1 : 0;
    cmd = DRV_IOR(NetRxPriorityChannelEn_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), ds));
    enable = GetNetRxPriorityChannelEn(V, enable_f, ds);
    tmp_value? CTC_BIT_SET(enable, mac_id[mac_num - 1]):
             CTC_BIT_UNSET(enable, mac_id[mac_num - 1]);
    SetNetRxPriorityChannelEn(V, enable_f, ds, enable);
    cmd = DRV_IOW(NetRxPriorityChannelEn_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), ds));
    /* DsNetRxBufAdmissionCtl per dp */

    /*5. copy origin mac obm(netrxbuf) cfg to new mac*/
    if (mac_num > 1)
    {
        cmd = DRV_IOR(DsNetRxBufAdmissionCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id[mac_num -1], DRV_CMD_DP_EN(cmd, dp_id), &adm_ctl));
        cmd = DRV_IOW(DsNetRxBufAdmissionCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id[0], DRV_CMD_DP_EN(cmd, dp_id), &adm_ctl));
    }

    return CTC_E_NONE;
}

int32
sys_at_port_set_xpipe_mode(uint8 lchip, uint32 gport, uint32 value)
{
    uint8  loop          = 0;
    uint8  step          = 0;
    uint8  index         = 0;
    uint8  dp_id         = 0;
    uint8  pp_id         = 0;
    uint8  txqm_id       = 0;
    uint8  mac_num       = 0;
    uint8  chan_num      = 0;
    uint16 sub_chan      = 0;
    uint16 split_en      = 0;
    uint16 chan_bmp      = 0;
    uint16 merge_en      = 0;
    uint16 identify_en   = 0;   /* set 1 base on source channel or cutthrough 0 base on pri + color */
    uint16 identify_mode = 0;   /* set 1 base on source channel 0 base on cutthrough */
    uint16 fallback_mode = 0;   /* set 1 base on queue map type 0 base on pri + color */
    uint32 cmd = 0;
    uint32 channel[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};    /* 0: low prio channel(origin channel), 1: middle prio channel 2: high prio channel */
    uint32 mac_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT]  = {0};    /* per dp mac client id value 0-31,0: low prio mac, 1: middle prio mac 2: high prio mac(origin mac) */
    uint32 mac_id_per_txqm[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
    uint32 guaranteeMode_mc = 0;
    uint32 tbl_id = 0;
    ds1_t ds;

    sal_memset(ds, 0, sizeof(ds1_t));

    CTC_ERROR_RETURN(sys_usw_port_api_get_mac(lchip, 0, gport, mac_id, &mac_num));
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 0, gport, channel, &chan_num));
    CTC_ERROR_RETURN(sys_usw_port_api_get_sub_chan_by_chan(lchip, 0, channel[0], &sub_chan, &pp_id, &dp_id));
    lchip = SYS_PP_BASE(lchip) + pp_id;

    for (loop = 0 ; loop < mac_num; loop++)
    {
        mac_id_per_txqm[loop] = mac_id[loop] % MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM);
    }
    txqm_id = (mac_id[mac_num - 1] / MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM));

    /*1. cfg nettx mapping NetTxPortSplitEnCtl(per  dp) DsNetTxPriorityPortRemap0(per dp TXQM0) */

    /*1.1 cfg nettx split */
    step = NetTxPortSplitEnCtl_portSplitEn1_f - NetTxPortSplitEnCtl_portSplitEn0_f;
    cmd = DRV_IOR(NetTxPortSplitEnCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), ds));
    split_en = GetNetTxPortSplitEnCtl(V, portSplitEn0_f + step * txqm_id, ds);
    (CTC_XPIPE_MODE_0 != value)? CTC_BIT_SET(split_en, mac_id_per_txqm[mac_num-1]): CTC_BIT_UNSET(split_en, mac_id_per_txqm[mac_num-1]);
    SetNetTxPortSplitEnCtl(V, portSplitEn0_f + step * txqm_id, ds, split_en);
    cmd = DRV_IOW(NetTxPortSplitEnCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_DP_EN(cmd, dp_id), ds));

    /*1.2 recod middel and high mac*/
    sal_memset(ds, 0, sizeof(ds1_t));
    step = DsNetTxPriorityPortRemap1_t - DsNetTxPriorityPortRemap0_t;
    tbl_id = DsNetTxPriorityPortRemap0_t + txqm_id * step;
    SetDsNetTxPriorityPortRemap0(V, highPriSubPort_f, ds, mac_num == 3? mac_id_per_txqm[1] : mac_id_per_txqm[0]);
    SetDsNetTxPriorityPortRemap0(V, lowPriSubPort_f,  ds, mac_id_per_txqm[0]);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id_per_txqm[mac_num-1], DRV_CMD_DP_EN(cmd, dp_id), ds));

    /*2. cfg mode, DsUcQWriteGuarantee (per pp)*/
    index = (channel[0] & 0x1FF) >> 4;
    CTC_BIT_SET(chan_bmp, channel[0] & 0xF);
    cmd = DRV_IOR(DsUcQWriteGuarantee_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, ds));

    merge_en      = GetDsUcQWriteGuarantee(V, mergeEn_f,      ds);
    identify_en   = GetDsUcQWriteGuarantee(V, identifyEn_f,   ds);
    identify_mode = GetDsUcQWriteGuarantee(V, identifyMode_f, ds);
    fallback_mode = GetDsUcQWriteGuarantee(V, fallbackMode_f, ds);

    merge_en = value? (merge_en | (chan_bmp)) : (merge_en & (~(chan_bmp)));
    if (CTC_XPIPE_MODE_0 == value)
    {
        identify_en   = identify_en   & (~chan_bmp);
        identify_mode = identify_mode & (~chan_bmp);
        fallback_mode = fallback_mode & (~chan_bmp);
    }
    else if (CTC_XPIPE_MODE_5 == value)
    {
        identify_en   = identify_en   | chan_bmp;
        identify_mode = identify_mode | chan_bmp;
        fallback_mode = fallback_mode & (~chan_bmp);
    }
    else
    {
        identify_en   = SYS_PORT_BASE_ON_PRI_COLOR(value) ? (identify_en   & (~chan_bmp)) : (identify_en   | chan_bmp);
        identify_mode = (CTC_XPIPE_MODE_3 == value)       ? (identify_mode & (~chan_bmp)) : (identify_mode | chan_bmp);
        fallback_mode = SYS_PORT_BASE_ON_PRI_COLOR(value) ? (fallback_mode & (~chan_bmp)) : (fallback_mode | chan_bmp);
    }

    SetDsUcQWriteGuarantee(V, mergeEn_f,      ds, merge_en);
    SetDsUcQWriteGuarantee(V, identifyEn_f,   ds, identify_en);
    SetDsUcQWriteGuarantee(V, identifyMode_f, ds, identify_mode);
    SetDsUcQWriteGuarantee(V, fallbackMode_f, ds, fallback_mode);
    cmd = DRV_IOW(DsUcQWriteGuarantee_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, ds));

    /* mcast only support CTC_XPIPE_MODE_1 and CTC_XPIPE_MODE_2 */
    /*3. set g_*_mode DsMcQWriteGuarantee(per core) */
    guaranteeMode_mc = (CTC_XPIPE_MODE_2 == value)? 1: 0;

    index = (channel[0] & 0x1FF) >> 4;

    cmd = DRV_IOR(DsMcQWriteGuarantee_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, ds));
    step = DsMcQWriteGuarantee_g_1_mode_f - DsMcQWriteGuarantee_g_0_mode_f;
    SetDsMcQWriteGuarantee(V, g_0_mode_f + step * (channel[0] & 0xF), ds, guaranteeMode_mc);
    cmd = DRV_IOW(DsMcQWriteGuarantee_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, ds));

    return CTC_E_NONE;
}

#endif


